using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using DDFileSyncPlugin;
using System.ServiceModel;
using System.Threading.Tasks;
using System.IO;

namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
      

        private FileSyncServiceHost fileServiceHost;
        private SyncType syncType = SyncType.SyncOff;
        private CloudDriveManagerRole persistentDriveManager = new CloudDriveManagerRole();
        private void RunSyncServices()
        {
            try
            {
                if (syncType != SyncType.SyncOff)
                {
                    if (syncType != SyncType.PeriodicSyncToStorageOnly)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            Trace.TraceInformation("Starting File Service Host");
                            StartFileSyncServiceHost();
                            Trace.TraceInformation("Started File Service Host");
                        });

                    }

                    if (syncType != SyncType.SyncToStorageOnlyOnFileEvent && syncType != SyncType.ReplicationOnly)
                    {
                        Task.Factory.StartNew(() =>
                            {
                                try
                                {
                                    Trace.TraceInformation("Starting Sync Service Continuously");
                                    SyncService.Instance.RunContinuously();
                                    Trace.TraceInformation("Started Sync Service Continuously");

                                }
                                catch (Exception ex)
                                {

                                    Trace.TraceError("Error starting sync engine (RunContinuously) " + ex.Message);
                                }
                            }
                      );
                    }

                }//if
            }
            catch (Exception ex)
            {

                Trace.TraceError("Error in Run() " + ex.Message);
            }
        }

        private void InitializeSyncServices()
        {
            syncType = GetConfiguredSyncType();

            if (syncType != SyncType.SyncOff)
            {
                try
                {
                    CreateTestDirs();

                    SyncService.Instance.OnStart(null);
                    Trace.TraceInformation("Initialized Sync Service");
                }
                catch (Exception ex)
                {

                    Trace.TraceError("Error starting sync engine (OnStart) " + ex.Message);
                }

            }
        }
        public override void Run()
        {
            // This is a sample worker implementation. Replace with your logic.
            Trace.WriteLine("Run entry point called", "Information");
          //  RunSyncServices();
            persistentDriveManager.Run();
            while (true)
            {
                Thread.Sleep(10000);

              
            }
        }

        public override bool OnStart()
        {
            // Set the maximum number of concurrent connections 
            ServicePointManager.DefaultConnectionLimit = 45;

            // For information on handling configuration changes
            // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
            SetupConfigurationSettingPublisher();

            SetupDiagnostics();
            Trace.TraceInformation("Setup Diagnostics");

          //  InitializeSyncServices();


            persistentDriveManager.OnStart();
            return base.OnStart();
        }


        private void CreateTestDirs()
        {
            string appRoot = Environment.GetEnvironmentVariable("RoleRoot") + @"\sitesroot";
            if (!System.IO.Directory.Exists(appRoot))
            {
                // May be WorkerRole
                appRoot = Environment.GetEnvironmentVariable("RoleRoot") + @"\approot";
            }

            FileUtils.SetFullControlDirectoryPermissions(appRoot);

            Directory.CreateDirectory(Path.Combine(appRoot, "ddtemp1"));
            Directory.CreateDirectory(Path.Combine(appRoot, "ddtemp2"));

        }
        private void StartFileSyncServiceHost()
        {

            try
            {
                fileServiceHost = new FileSyncServiceHost() {
                    FileStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("com.dynamicdeploy.ddfilesync.DataConnectionString")),
                  DdSyncType = syncType
                };
                fileServiceHost.StartService(3);
                Trace.TraceInformation("Started file service host.");
            }
            catch (Exception ex)
            {

                Trace.TraceError("Error starting sync engine (OnStart) " + ex.Message);
            }

        }


        private SyncType GetConfiguredSyncType()
        {
            SyncType st;
            if (!Enum.TryParse<SyncType>(RoleEnvironment.GetConfigurationSettingValue("com.dynamicdeploy.ddfilesync.SyncType"), out st))
            {

                Trace.TraceError("Could not parse SyncType. Turning synchronization off.");
                st = SyncType.SyncOff;

            }

            return st;

        }
        private void SetupConfigurationSettingPublisher()
        {
            // This code sets up a handler to update CloudStorageAccount instances when their corresponding
            // configuration settings change in the service configuration file.
            Trace.TraceInformation("Setting up configuration setting publishing");
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                // Provide the configSetter with the initial value
                configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));

                RoleEnvironment.Changed += (sender, arg) =>
                {
                    if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
                        .Any((change) => (change.ConfigurationSettingName == configName)))
                    {
                        // The corresponding configuration setting has changed, propagate the value
                        if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
                        {
                            // In this case, the change to the storage account credentials in the
                            // service configuration is significant enough that the role needs to be
                            // recycled in order to use the latest settings. (for example, the 
                            // endpoint has changed)
                            RoleEnvironment.RequestRecycle();
                        }
                    }
                };
            });
        }

        private void SetupDiagnostics()
        {
            Trace.WriteLine("Setting up diagnostics", "Information");

            DiagnosticMonitorConfiguration diagConfig = DiagnosticMonitor.GetDefaultInitialConfiguration();

            string logLevel = RoleEnvironment.GetConfigurationSettingValue("LogLevel").ToLower();

            int debugMinutes = 2;
            int errorMinutes = 60;
            if (logLevel == "debug")
            {
                diagConfig.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
                diagConfig.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
                diagConfig.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Verbose;

                diagConfig.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);
                diagConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);
                diagConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);

                Microsoft.WindowsAzure.Diagnostics.CrashDumps.EnableCollection(true);

                //Event Logs
                // Add event collection from the Windows Event Log
                diagConfig.WindowsEventLog.DataSources.Add("System!*");
                diagConfig.WindowsEventLog.DataSources.Add("Application!*");
                diagConfig.WindowsEventLog.DataSources.Add("Security!*");

                diagConfig.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);

            }

            else if (logLevel == "info")
            {
                diagConfig.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = LogLevel.Information;
                diagConfig.Logs.ScheduledTransferLogLevelFilter = LogLevel.Information;
                diagConfig.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Information;

                diagConfig.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);
                diagConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);
                diagConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);

                //Event Logs
                // Add event collection from the Windows Event Log
                diagConfig.WindowsEventLog.DataSources.Add("System!*");
                diagConfig.WindowsEventLog.DataSources.Add("Application!*");
                diagConfig.WindowsEventLog.DataSources.Add("Security!*");

                diagConfig.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(debugMinutes);

                Microsoft.WindowsAzure.Diagnostics.CrashDumps.EnableCollection(true);
            }
            else if (logLevel == "error")
            {
                // diagConfig.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = LogLevel.Error;
                diagConfig.Logs.ScheduledTransferLogLevelFilter = LogLevel.Error;
                //  diagConfig.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Error;
                diagConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(errorMinutes);
                diagConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(errorMinutes);
            }

            // Add performance counter monitoring for configured counters
            // Run typeperf.exe /q to query the counter list 
            string perfCounterString = RoleEnvironment.GetConfigurationSettingValue("PerformanceCounters");

            if (!string.IsNullOrEmpty(perfCounterString))
            {
                IList<string> perfCounters = perfCounterString.Split(',').ToList();

                // Setup each counter specified in comma delimitered string
                foreach (string perfCounter in perfCounters)
                {
                    diagConfig.PerformanceCounters.DataSources.Add(
                        new PerformanceCounterConfiguration
                        {
                            CounterSpecifier = perfCounter,
                            SampleRate = TimeSpan.FromSeconds(errorMinutes * 2)
                        }
                        );
                }

                // Update counter information in Azure every 30 seconds
                diagConfig.PerformanceCounters.ScheduledTransferPeriod = TimeSpan.FromMinutes(errorMinutes);
            }

            diagConfig.ConfigurationChangePollInterval = TimeSpan.FromMinutes(errorMinutes);



            // Start the diagnostic monitor with this custom configuration 
            DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", diagConfig);
        }
    }
}
